Skip to content

Backport #1935: [swc-plugin] Capture lexical this for nested arrow step functions#1945

Open
github-actions[bot] wants to merge 1 commit intostablefrom
backport/pr-1935-to-stable
Open

Backport #1935: [swc-plugin] Capture lexical this for nested arrow step functions#1945
github-actions[bot] wants to merge 1 commit intostablefrom
backport/pr-1935-to-stable

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 5, 2026

Automated backport of #1935 to stable.

Triggered by the backport-stable label.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.7). Please review the conflict resolution carefully before merging.

…1935)

* [swc-plugin] Capture lexical `this` for nested arrow step functions

When a nested arrow `"use step"` references the enclosing function/method's
`this`, plumb that `this` through the workflow runtime so the step body
sees the correct receiver.

- Workflow mode wraps the step proxy with `.bind(this)`, so invoking the
  proxy captures the caller's `this` as `thisVal` on the queue item.
- Step mode hoists the body as a regular `function` (not an arrow) so the
  runtime's `stepFn.apply(thisVal, args)` rebinds `this` inside the
  hoisted body.

Detection only fires for arrows, since arrows inherit `this` lexically.
Nested non-arrow functions/methods/getters/setters introduce their own
`this`, so the detector stops at those boundaries.

The runtime already supported `thisVal` for instance-method steps; this
PR is purely a compiler change to feed the existing pipeline.

Caveat: capture works at runtime only when the captured value is
serializable across the workflow->step boundary (i.e. the enclosing
class implements `WORKFLOW_SERIALIZE`/`WORKFLOW_DESERIALIZE`).

Refs #1865

* Address PR review: preserve step proxy metadata + tighter `this` detection

- core: Override `.bind` on step proxies so the bound function retains
  `stepId` and `__closureVarsFn`. Without this, a bound proxy that flows
  through workflow serialization (e.g. as a step argument) would be
  treated as a non-serializable plain function by `getStepFunctionReducer`.
- swc-plugin: Detector now also walks `arrow.params` so `this` references
  in default values / destructuring initializers (e.g. `(x = this.foo) =>
  ...`) trigger the `.bind(this)` path.
- swc-plugin: Class bodies inside the arrow body are now treated as
  `this`-binding boundaries — `this` inside class field initializers,
  methods, etc. is bound to the class instance, not the outer arrow. The
  detector still walks `extends` clauses and computed property keys
  because those are evaluated in the surrounding scope.
- spec.md: Sharpen the note about `this` in step bodies — it's
  syntactically allowed but only meaningful for instance-method steps and
  lexical-`this` arrow steps; other shapes compile but `this` will be
  whatever the caller of the step proxy passes.
- Add `lexical-this-detector-edge-cases` fixture covering both the
  default-param positive case and the inner-class false-positive guard.
- Strengthen the runtime test to assert `stepId` / `__closureVarsFn`
  survive `.bind(...)`.

* [swc-plugin] Fix `arguments` closure-var capture; drop dead `this`/`arguments` checks

- Add `arguments` to `is_global_identifier` so it's not captured as a
  closure variable. Previously a nested `function`-form step like

      function step() { 'use step'; return arguments[0]; }

  was hoisted with `const { arguments } = ...` (a strict-mode syntax
  error) and the body's `arguments[0]` resolved against the destructured
  binding instead of the function's intrinsic `arguments` object.
- Remove dead `ForbiddenExpression` checks for `this` and `arguments` in
  `visit_mut_this_expr` / `visit_mut_ident`. The `'use step'` /
  `'use workflow'` directives are stripped during the module-level
  traversal before children are visited, so `in_step_function` /
  `in_workflow_function` are never observed as true here in practice.
  The existing `step-with-this-arguments-super` fixture explicitly
  documents that all three identifiers are allowed in step bodies.
- Tighten the spec note about `arguments` accordingly: it works in
  `function`-form steps (reflecting positional args) but is not captured
  for arrow-form steps; use `...args` for that case.
- Add `nested-step-arguments` fixture pinning down the new behavior.

Signed-off-by: Nathan Rajlich <n@n8.io>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 5, 2026

🦋 Changeset detected

Latest commit: c472135

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@workflow/core Patch
@workflow/swc-plugin Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/web Patch
workflow Patch
@workflow/world-testing Patch
tarballs Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/nuxt Patch
@workflow/ai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment May 5, 2026 9:18pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment May 5, 2026 9:18pm
example-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-astro-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-express-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-fastify-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-hono-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-nitro-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-nuxt-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-sveltekit-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-tanstack-start-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workbench-vite-workflow Ready Ready Preview, Comment May 5, 2026 9:18pm
workflow-docs Ready Ready Preview, Comment, Open in v0 May 5, 2026 9:18pm
workflow-swc-playground Ready Ready Preview, Comment May 5, 2026 9:18pm
workflow-tarballs Ready Ready Preview, Comment May 5, 2026 9:18pm
workflow-web Ready Ready Preview, Comment May 5, 2026 9:18pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants